package com.meme.editor.model.sprite2d;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ListIterator;

import org.apache.log4j.Logger;

import com.meme.editor.EntityRefLink;
import com.meme.editor.PropertyValueModification;
import com.meme.editor.PropertyValueModificationList;
import com.meme.editor.property.PropertyFactory;
import com.meme.util.MathUtil;

import com.meme.editor.EntityObject;


public class Tiled2dModule extends ModuleRef
{
	static Logger logger = Logger.getLogger (Tiled2dModule.class);
	
	
	final static String GroupName_Tiled2dModuleGroup = "Tiled Module";
//	final static String PropertyName_CellRow        = "Cell Row";
//	final static String PropertyName_CellCol        = "Cell Col";
	final static String PropertyName_FlipX        = "Flip X";
	final static String PropertyName_FlipY        = "Flip Y";
	final static String PropertyName_Palette        = "Palette";

	
	
	
	int mCellRow;
	int mCellCol;	
	
	boolean mFlipX;
	boolean mFlipY;
	int mPaletteID;

	protected Tiled2dModule (int cellRow, int cellCol)
	{
		this (null, cellRow, cellCol, 0);
	}
	
	public Tiled2dModule (Tiled2dGrid grid, int cellRow, int cellCol)
	{
		this (grid, cellRow, cellCol, 0);
	}
	
	public Tiled2dModule (Tiled2dGrid grid, int cellRow, int cellCol, int palID)
	{
		super (cellRow + ", " + cellCol, grid);
		
		getPublicProperty (EntityObject.GroupName_Entity, EntityObject.PropertyName_Name)
			.setEditable(false);
		
		createPropertyGroup (GroupName_Tiled2dModuleGroup);
//		createPublicProperty (GroupName_Tiled2dModuleGroup, PropertyName_CellRow, PropertyFactory.ValueType_Number )
//			.setEditable (false);
//		createPublicProperty (GroupName_Tiled2dModuleGroup, PropertyName_CellCol, PropertyFactory.ValueType_Number )
//			.setEditable (false);
		createPublicProperty (GroupName_Tiled2dModuleGroup, PropertyName_FlipX, PropertyFactory.ValueType_Boolean );
		createPublicProperty (GroupName_Tiled2dModuleGroup, PropertyName_FlipY, PropertyFactory.ValueType_Boolean );
		createPublicProperty (GroupName_Tiled2dModuleGroup, PropertyName_Palette, PropertyFactory.ValueType_Number );

		setModule    (null);
		setPaletteID (palID);		
		setFlipX (false);
		setFlipY (false);
		
		setPosInGrid (cellRow, cellCol);
	}
	
	@Override
	public String getDefaultName ()
	{
		return "Tile";
	}
	
	@Override
	protected void _handleModifyingPropertyValues (PropertyValueModificationList modications)
	{		
		ListIterator<PropertyValueModification> iter = modications.listIterator();
		while ( iter.hasNext() )
		{
			PropertyValueModification mod = iter.next();
			
			if (   mod.mGroupName.equals (GroupName_Tiled2dModuleGroup) )
			{
				if ( mod.mPropertyName.equals (PropertyName_FlipX) )
				{
					setFlipX (( (Boolean) (mod.mNewValue) ).booleanValue());
					iter.remove();
				}
				else if ( mod.mPropertyName.equals (PropertyName_FlipY) )
				{
					setFlipY (( (Boolean) (mod.mNewValue) ).booleanValue());
					iter.remove();
				}
				else if ( mod.mPropertyName.equals (PropertyName_Palette) )
				{
					setPaletteID (( (Float) (mod.mNewValue) ).intValue());
					iter.remove();
				}
			}
		}
			
		super._handleModifyingPropertyValues (modications);
	}	
	
	public Tiled2dGrid getGridContainer ()
	{
		EntityObject parent = getParent ();
		
		logger.assertLog (parent != null, "parent should not be null.");
		
		return (Tiled2dGrid) parent;
	}
	
	
	public void setPosInGrid (int cellRow, int cellCol)
	{
		if ( getParent () == null )
		{
			mCellRow = cellRow;
			mCellCol = cellCol;
			return;
		}
		
		int gridRows = getGridContainer ().getCellRows();
		int gridCols = getGridContainer ().getCellCols();
		
		mCellRow = MathUtil.clipValue(cellRow, 0, gridRows);
		mCellCol = MathUtil.clipValue(cellCol, 0, gridCols);
		
		setName (mCellRow + ", " + mCellCol);
		
//		changePublicPropertyValue ( GroupName_Tiled2dModuleGroup, PropertyName_CellRow, mCellRow );
//		changePublicPropertyValue ( GroupName_Tiled2dModuleGroup, PropertyName_CellCol, mCellCol );
	}
	
	public int getRow ()
	{
		return mCellRow;
	}
	
	public int getCol ()
	{
		return mCellCol;
	}
	

	public void setFlipX (boolean flip)
	{
		mFlipX = flip;
		changePublicPropertyValue ( GroupName_Tiled2dModuleGroup, PropertyName_FlipX, new Boolean (mFlipX) );
	}
	
	public boolean isFlipX ()
	{
		return mFlipX;
	}
	
	public void setFlipY (boolean flip)
	{
		mFlipY = flip;
		changePublicPropertyValue ( GroupName_Tiled2dModuleGroup, PropertyName_FlipY, new Boolean (mFlipY) );
	}
	
	public boolean isFlipY ()
	{
		return mFlipY;
	}

	public void setPaletteID (int palID)
	{
		mPaletteID = palID;
		changePublicPropertyValue ( GroupName_Tiled2dModuleGroup, PropertyName_Palette, new Float (mPaletteID) );
	}
	
	public int getPaletteID ()
	{
		return mPaletteID;
	}
	
	@Override
	public boolean isValid ()
	{
		if ( getModule () == null )
			return false;
		
		return getModule ().isValid();
	}

	
	@Override
	public int getMinX ()
	{
		return 0;
	}
	
	@Override
	public int getMinY ()
	{
		return 0;
	}
	
	@Override
	public int getWidth ()
	{
		return getGridContainer ().getCellWidth();
	}
	
	@Override
	public int getHeight ()
	{
		return getGridContainer ().getCellHeight();
	}
	
	@Override
	public void render (Graphics2D g, int posX, int posY, boolean flipX, boolean flipY, int scale, int flags)
	{
		if ( isValid () )
		{
			Rectangle bounds = g.getClipBounds();
			g.setClip(posX, posY, getWidth () * scale, getHeight () * scale);
			if (bounds != null)
				g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);

			flipX ^= isFlipX ();
			flipY ^= isFlipY ();
			
			Module module = getModule ();
			if ( ! ( module instanceof Tiled2dModule ) )
			{
				if (flipX) posX += getWidth  () * scale;
				if (flipY) posY += getHeight () * scale;
			}
			
			module.render(g, posX, posY, flipX, flipY, scale, flags);

			g.setClip (bounds);
		}
	}
	
}
